/**
 * 
 */
package org.wordml.core.util;

import java.io.OutputStream;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

import org.wordml.core.encoding.XmlEnconding;

/**
 * Serialize JAXB objects based on the Microsoft Word XSD files
 * @author juan.c.garciamatos
 *
 */
public enum JAXBSerializer{
	CTX;
	private JAXBContext instance;
	private JAXBSerializer() {
		StringBuilder wordmlPackages = new StringBuilder();
		wordmlPackages.append("com.microsoft.schemas.aml._2001.core:")
		.append("com.microsoft.schemas.office.office:")
		.append("com.microsoft.schemas.office.word:")
		.append("com.microsoft.schemas.office.word._2003.auxhint:")
		.append("com.microsoft.schemas.office.word._2003.wordml:")
		.append("com.microsoft.schemas.office.word._2003.wordml.sp2:")
		.append("com.microsoft.schemas.schemalibrary._2003.core:")
		.append("com.microsoft.schemas.vml");
		try {
			instance = JAXBContext.newInstance(wordmlPackages.toString());
		} catch (JAXBException e) {}
	}
	
	/**
	 * Serialize a JAXB object into the specified Outputstream using the Xml Enconding that was sent
	 * @param <T> is the parametrized of type of the rootObject
	 * @param stream is the target outputstream
	 * @param rootObject if the object to serialize
	 * @throws SerializationException
	 */
	public <T> void  serializeObject(OutputStream stream, T rootObject)
		throws SerializationException{
		serializeObject(stream, rootObject, XmlEnconding.UTF8, false);
	}
	
	/**
	 * Serialize a JAXB object into the specified Outputstream using the Xml Enconding that was sent
	 * @param <T> is the parametrized of type of the rootObject
	 * @param stream is the target outputstream
	 * @param rootObject if the object to serialize
	 * @param encoding define the xml enconding
	 * @throws SerializationException
	 */
	public <T> void  serializeObject(OutputStream stream, T rootObject, XmlEnconding encoding) 
		throws SerializationException{
		serializeObject(stream, rootObject, encoding, false);
	}
	
	/**
	 * Serialize a JAXB object into the specified Outputstream using the Xml Enconding that was sent
	 * @param <T> is the parametrized of type of the rootObject
	 * @param stream is the target outputstream
	 * @param rootObject if the object to serialize
	 * @param encoding define the xml enconding
	 * @param pretty is for making the output nice, useful when debuging.
	 * @throws SerializationException
	 */
	public <T> void  serializeObject(OutputStream stream, T rootObject, XmlEnconding encoding, boolean pretty) 
		throws SerializationException{
		Marshaller m;
		try {
			m = instance.createMarshaller();
//			m.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
			m.setProperty(Marshaller.JAXB_ENCODING, encoding.getEncoding());
			m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.valueOf(pretty));
			m.marshal(rootObject, stream);
		} catch (JAXBException e) {
			throw new SerializationException(e);
		}
	}
}